{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A simple DNN model built in Keras.\n",
    "\n",
    "In this notebook, we will use the ML datasets we read in with our Keras pipeline earlier and build our Keras DNN to predict the fare amount for NYC taxi cab rides.\n",
    "\n",
    "### Learning objectives\n",
    "1. Review how to read in CSV file data using tf.data\n",
    "2. Specify input, hidden, and output layers in the DNN architecture\n",
    "3. Review and visualize the final DNN shape\n",
    "4. Train the model locally and visualize the loss curves\n",
    "5. Deploy and predict with the model using Cloud AI Platform \n",
    "\n",
    "Each learning objective will correspond to a __#TODO__ in the [student lab notebook](../labs/keras_dnn.ipynb) -- try to complete that notebook first before reviewing this solution notebook. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!sudo chown -R jupyter:jupyter /home/jupyter/training-data-analyst"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install tensorflow==2.1 --user"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please ignore any compatibility warnings and errors.\n",
    "Make sure to <b>restart</b> your kernel to ensure this change has taken place."
  ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "export PROJECT=$(gcloud config list project --format \"value(core.project)\")\n",
    "echo \"Your current GCP Project Name is: \"$PROJECT\n",
    "gcloud config set ai_platform/region global"
  ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TensorFlow version:  2.1.0\n"
     ]
    }
   ],
   "source": [
    "import os, json, math\n",
    "import numpy as np\n",
    "import shutil\n",
    "import tensorflow as tf\n",
    "print(\"TensorFlow version: \",tf.version.VERSION)\n",
    "\n",
    "PROJECT = \"your-gcp-project-here\" # REPLACE WITH YOUR PROJECT NAME\n",
    "REGION = \"us-central1\" # REPLACE WITH YOUR BUCKET REGION e.g. us-central1\n",
    "\n",
    "# Do not change these\n",
    "os.environ[\"PROJECT\"] = PROJECT\n",
    "os.environ[\"REGION\"] = REGION\n",
    "os.environ[\"BUCKET\"] = PROJECT # DEFAULT BUCKET WILL BE PROJECT ID\n",
    "os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # SET TF ERROR LOG VERBOSITY\n",
    "\n",
    "if PROJECT == \"your-gcp-project-here\":\n",
    "  print(\"Don't forget to update your PROJECT name! Currently:\", PROJECT)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "## Create GCS bucket if it doesn't exist already...\n",
    "exists=$(gcloud storage ls | grep -w gs://${PROJECT}/)\n",    "\n",
    "if [ -n \"$exists\" ]; then\n",
    "   echo -e \"Bucket exists, let's not re-create it. \\n\\nHere are your buckets:\"\n",
    "   gcloud storage ls\n",    "    \n",
    "else\n",
    "   echo \"Creating a new GCS bucket.\"\n",
    "   gcloud storage buckets create --location ${REGION} gs://${PROJECT}\n",    "   echo \"\\nHere are your current buckets:\"\n",
    "   gcloud storage ls\n",    "fi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Locating the CSV files\n",
    "\n",
    "We will start with the CSV files that we wrote out in the [first notebook](../01_explore/taxifare.iypnb) of this sequence. Just so you don't have to run the notebook, we saved a copy in ../../data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rw-r--r-- 1 jupyter jupyter 123590 Sep 12 16:33 ../data/taxi-test.csv\n",
      "-rw-r--r-- 1 jupyter jupyter 579055 Sep 12 16:33 ../data/taxi-train.csv\n",
      "-rw-r--r-- 1 jupyter jupyter 123114 Sep 12 16:33 ../data/taxi-valid.csv\n"
     ]
    }
   ],
   "source": [
    "!ls -l ../../data/*.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Use tf.data to read the CSV files\n",
    "\n",
    "We wrote these cells in the [third notebook](../03_tfdata/solution/input_pipeline.ipynb) of this sequence where we created a data pipeline with Keras.\n",
    "\n",
    "First let's define our columns of data, which column we're predicting for, and the default values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "CSV_COLUMNS  = ['fare_amount',  'pickup_datetime',\n",
    "                'pickup_longitude', 'pickup_latitude', \n",
    "                'dropoff_longitude', 'dropoff_latitude', \n",
    "                'passenger_count', 'key']\n",
    "LABEL_COLUMN = 'fare_amount'\n",
    "DEFAULTS     = [[0.0],['na'],[0.0],[0.0],[0.0],[0.0],[0.0],['na']]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, let's define our features we want to use and our label(s) and then load in the dataset for training."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def features_and_labels(row_data):\n",
    "    for unwanted_col in ['pickup_datetime', 'key']:\n",
    "        row_data.pop(unwanted_col)\n",
    "    label = row_data.pop(LABEL_COLUMN)\n",
    "    return row_data, label  # features, label\n",
    "\n",
    "# load the training data\n",
    "def load_dataset(pattern, batch_size=1, mode=tf.estimator.ModeKeys.EVAL):\n",
    "  dataset = (tf.data.experimental.make_csv_dataset(pattern, batch_size, CSV_COLUMNS, DEFAULTS)\n",
    "             .map(features_and_labels) # features, label\n",
    "             )\n",
    "  if mode == tf.estimator.ModeKeys.TRAIN:\n",
    "        dataset = dataset.shuffle(1000).repeat()\n",
    "  dataset = dataset.prefetch(1) # take advantage of multi-threading; 1=AUTOTUNE\n",
    "  return dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Build a DNN with Keras\n",
    "\n",
    "Now let's build the Deep Neural Network (DNN) model in Keras and specify the input and hidden layers. We will print out the DNN architecture and then visualize it later on."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Here is our DNN architecture so far:\n",
      "\n",
      "Model: \"model_3\"\n",
      "__________________________________________________________________________________________________\n",
      "Layer (type)                    Output Shape         Param #     Connected to                     \n",
      "==================================================================================================\n",
      "dropoff_latitude (InputLayer)   [(None,)]            0                                            \n",
      "__________________________________________________________________________________________________\n",
      "dropoff_longitude (InputLayer)  [(None,)]            0                                            \n",
      "__________________________________________________________________________________________________\n",
      "passenger_count (InputLayer)    [(None,)]            0                                            \n",
      "__________________________________________________________________________________________________\n",
      "pickup_latitude (InputLayer)    [(None,)]            0                                            \n",
      "__________________________________________________________________________________________________\n",
      "pickup_longitude (InputLayer)   [(None,)]            0                                            \n",
      "__________________________________________________________________________________________________\n",
      "dense_features_3 (DenseFeatures (None, 5)            0           dropoff_latitude[0][0]           \n",
      "                                                                 dropoff_longitude[0][0]          \n",
      "                                                                 passenger_count[0][0]            \n",
      "                                                                 pickup_latitude[0][0]            \n",
      "                                                                 pickup_longitude[0][0]           \n",
      "__________________________________________________________________________________________________\n",
      "h1 (Dense)                      (None, 32)           192         dense_features_3[0][0]           \n",
      "__________________________________________________________________________________________________\n",
      "h2 (Dense)                      (None, 8)            264         h1[0][0]                         \n",
      "__________________________________________________________________________________________________\n",
      "fare (Dense)                    (None, 1)            9           h2[0][0]                         \n",
      "==================================================================================================\n",
      "Total params: 465\n",
      "Trainable params: 465\n",
      "Non-trainable params: 0\n",
      "__________________________________________________________________________________________________\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "## Build a simple Keras DNN using its Functional API\n",
    "def rmse(y_true, y_pred):\n",
    "    return tf.sqrt(tf.reduce_mean(tf.square(y_pred - y_true))) \n",
    "\n",
    "def build_dnn_model():\n",
    "    INPUT_COLS = ['pickup_longitude', 'pickup_latitude', \n",
    "                  'dropoff_longitude', 'dropoff_latitude', \n",
    "                  'passenger_count']\n",
    "\n",
    "    # input layer\n",
    "    inputs = {\n",
    "        colname : tf.keras.layers.Input(name=colname, shape=(), dtype='float32')\n",
    "           for colname in INPUT_COLS\n",
    "    }\n",
    "    feature_columns = {\n",
    "        colname : tf.feature_column.numeric_column(colname)\n",
    "           for colname in INPUT_COLS\n",
    "    }\n",
    "    \n",
    "    # the constructor for DenseFeatures takes a list of numeric columns\n",
    "    # The Functional API in Keras requires that you specify: LayerConstructor()(inputs)\n",
    "    dnn_inputs = tf.keras.layers.DenseFeatures(feature_columns.values())(inputs)\n",
    "\n",
    "    # two hidden layers of [32, 8] just in like the BQML DNN\n",
    "    h1 = tf.keras.layers.Dense(32, activation='relu', name='h1')(dnn_inputs)\n",
    "    h2 = tf.keras.layers.Dense(8, activation='relu', name='h2')(h1)\n",
    "\n",
    "    # final output is a linear activation because this is regression\n",
    "    output = tf.keras.layers.Dense(1, activation='linear', name='fare')(h2)\n",
    "    model = tf.keras.models.Model(inputs, output)\n",
    "    model.compile(optimizer='adam', loss='mse', metrics=[rmse, 'mse'])\n",
    "    return model\n",
    "\n",
    "print(\"Here is our DNN architecture so far:\\n\")\n",
    "model = build_dnn_model()\n",
    "print(model.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize the DNN\n",
    "\n",
    "We can visualize the DNN using the Keras [plot_model](https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/utils/plot_model) utility."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+sAAAFhCAYAAAAItDveAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOzdeVhV1d4H8O9hkkkmERFREUW8oTmUmAmaBb63QRsUsHJIUdByxFRSM800veWMQ+rN2QyzV6QyBzRSwjTT1JzykoCoIIogMxx+7x++7AvKcIAD54Dfz/Oc59F19l77t9dee53zY++1j0pEBERERERERESkL3YZ6DoCIiIiIiIiIiqNyToRERERERGRnmGyTkRERERERKRnmKwTERERERER6Rmjqiy8a9cu7Nq1q7ZiIaJqcHZ2xpIlS3QdBhERERERaVGVrqzv2rULsbGxtRULEVVRYmIili5dquswiIiIiIhIy6p0ZR0AevbsifDw8NqIhYiqKDw8HAEBAboOg4iIiIiItIxz1omIiIiIiIj0DJN1IiIiIiIiIj3DZJ2IiIiIiIhIzzBZJyIiIiIiItIzTNaJiIiIiIiI9AyTdSIiIiIiIiI9w2SdiIiIiIiISM8wWSciIiIiIiLSM0zWiYiIiIiIiPQMk3UiIiIiIiIiPcNknYiIiIiIiEjPMFknIiIiIiIi0jNM1omIiIiIiIj0DJN1IiIiIiIiIj2js2T93r17utp0nUlOTkZ4eDjmz5+v61Aq9TgcDyIiIiIiovqiTpP13NxczJ8/Hz179kSTJk3qctMaERGsWLEC06dPR9++feHt7Y3Lly+XW16Rixcv4uOPP0ZAQAC2bt1a49h69OiBqVOn1riekmrzeBw9ehShoaFQqVRQqVQYNmwYIiIitLqN6jhy5Aj8/PyUuIKDgxETE6PrsIiIiIiIiEpRiYhourC/vz8AIDw8vNobzMnJQYsWLZCWloYqbLpOLF++HDNnzsS9e/eQmZmJkSNHIjQ0FLGxsWWWe3p6Vlhfbm4uzMzM4O7ujkuXLmkcR2JiIlq2bFmqbPDgwXBzc8O8efMqXK6qavt4tG7dGgkJCcjKyoK5ubnW69fEw+2UnZ0NCwsLtGrVCvHx8TqJSVvCw8MREBCgd+cSERERERHVyC6jut6imZkZHBwckJaWVtebrtSaNWvQokULGBkZwcbGBt9++y0AYNiwYWWWV8bU1LTKMfz9998YNmwYjh49Wqp8586dGi1XVbV9PMzMzABAZ4l6We1UHEtxbERERERERPqGD5grITExESqVSuNybbt+/TpeeeUV3L59WyvLPe7YTkREREREVF/VerKenZ2NkJAQBAUFYdasWfjggw+QlZUFAFCr1fjpp58wadIkuLi4ICkpCX369EGrVq2QlpaG9PR0TJs2DaGhoQgJCUG/fv0QEhKi3LIdGxuLKVOmwMXFBbdu3cLAgQNhZ2eHjh07Yvfu3UoMFdUDAN999x3GjBmD7Oxs3Lp1C2PGjMGYMWOwc+fOMsszMzOr3R5XrlzBoEGDMH36dAwdOhTe3t44e/YsAGDTpk24cOGCsq3iNgoPD8fw4cPRu3fvcpdbt26dMg8bADIyMrB48eJSZZUdj2I5OTlYtGgRAgMD8fTTT8PHxwfnzp1T3j98+DCcnZ0RHR1dpX0XEURERCAoKAjOzs5IS0vD8OHD0aRJE3Ts2BG//fabxsdVk/0tq52qqqLjtW3bNpibm0OlUmHhwoUoLCwEAGzfvh0mJibYtGlThe1ZWf8nIiIiIqLHmFSBn5+f+Pn5abx8QUGBeHp6yqhRo6SoqEhERK5evSqGhoYCQHJzcyUmJkbMzMwEgCxYsEAOHjwogYGBcuPGDXFzc5OPPvpIqS85OVnc3NykTZs2kpqaKpGRkWJqaioAZNy4cRIdHS3bt28XS0tLASDHjh2TjIyMCutJS0tTygGIu7v7I/tRXrkmHl63Xbt24urqKiIi+fn5Ym1tLR4eHhVuKz4+/pHyspZzdXWVhw9pybLKjkexUaNGycWLF5X/+/r6ioODg6Snp4uIyJ49e8TMzEz27t1b6f67u7srdRcVFUliYqJYWFgIAPnkk0/k2rVrsnXrVgEgnp6eUlhYqNFx1WR/y2unisofVtnxmjlzpgCQ8+fPK2Xx8fHy2muvKf8vrz1TUlLK7f/379+vNDYRka+//vqRNiAiIiIionovvFaT9ZUrVwoAuXDhQqlyNze3UglG+/btBYDcuXNHKZsxY4YAkBs3bpRad/PmzQJApk6dWqquzMxMZZmlS5cKAAkICNC4HpG6SdYXL14sO3bsEBERtVotrq6uYmRkVOG2ioqKNErWSybGZZVpcjyOHz8uAMp8RUZGKusUFBRotP9lxVR8vEvun4ODg5iYmDwSU3nHVZP9Fan5Ma3seKWmpoqlpaWMGjVKKVuwYIHSVpq0Z1n9X1NM1omIiIiIGqTwWn3A3IEDBwAALi4upcoNDErffV9827KdnZ1SVvxzWo0bNy61bPGt4L/88kupuiwsLJRlBgwYgMmTJ+Ovv/7CrVu3NKqnroSEhCAzMxOrVq3C3bt3kZeXp9w+XR5tzZfX5HicPHkSHh4eOH/+fIV1GRlVv+s8vD8qlQq2trZISUl5JKbyjmtdqex4NWnSBOPHj8fnn3+OOXPmwMnJCVFRUcrP7GnSnmX1fyIiIiIierzV6pz1pKQkAMCdO3eqvG5xsnbt2rVS5c2aNQMAWFtbl7uuk5MTAKBly5Y1qqc2nDhxAp06dYKrqys+/PBDWFpa1tm2NTked+7cQVxc3CPz2IEH8+d1qeRxrW0pKSkoKCjQ6HiFhITAxMQEy5Ytw6lTp+Dp6an8MUOf25OIiIiIiPRXrSbrHTp0AAB8//33VV63+Mr3w+smJiYCAHx8fMpdtzgZ9fHxqVE9tWHYsGEoKCjAiy++CAAoKioCgFK/k13Zlfbyliu+QpuXl6fUnZ6ertSvyfHo0KGD8kC0ki5cuICwsLAqx6hNJY8rUPn+FqtqrCKCd999F4aGhhodL3t7e4wdOxZr167FihUrMHLkSOU9TduTiIiIiIiopFpN1qdOnQpDQ0PMmDEDP/74I7Kzs3H48GHcuHEDwIPfwAaA3NxcACj1lPVp06bBw8MDK1euxM2bN5XyVatW4dlnn8W4ceNKbatkQnbo0CF069YNwcHBGtdz9+5dAEB+fn6pessr10R2dnap/QOAmzdvIikpCQcOHMD27dtx7949AA+uuCcmJqJt27a4efMmEhISlHXu378P4METz4uVtVxxMv7JJ5/gr7/+wvLly5VEdv/+/QgJCan0eLz66qto06YN5s2bh5EjR2L79u2YNWsWJk2ahBEjRgB48PR8Gxsb7Nu3T+M2KHllubg9Sia8xftYUFBQav3yjqsm+6tWq8tsp+L9vX//vpJ8F0tPT0dwcDBMTU1hYGBQ6fEqNmXKFOTn5yMhIQHt2rVTyjVpz7L6PxERERERPd4M58yZM0fThXft2gUA8PPz02h5R0dHPPfcc/jjjz8QFhaGzZs3w9HREffv38eLL74Ia2tr7NixA3v37gUApKamwtnZGc2bN4exsTGGDh2KtLQ0rF27FmfOnEFUVBRsbGywfv16mJiYAADCwsJw584dWFlZoX379sjMzMTRo0exZs0amJmZaVTPuXPnsHDhQpw6dUq5Mmtra4vbt2+XWe7o6FjpvsfFxeGTTz7BiRMnkJ6eDhsbG7i7u8PBwQHHjh3D2bNn8fbbb8PV1RXHjx9HQkICBg0ahPT0dFy8eBFdunTBE088gaysLMyfPx/Hjh1DZmYmrKys4OHhgbt375ZaDgC6deuGEydOICIiAufOncOkSZMQGxuL3r17o1WrVujTpw98fHzKPR5OTk5o27YtXn/9dcTFxeHAgQOIioqCs7MzVq1apcypjo+Px759++Dv7482bdqUuf/Fx+CHH34A8GAagpGREaKiovDVV18BeDDvvXPnzli7di2++eYbAA/+KNKrVy988cUXFR5XTfbX3d0dt2/fLtVOhw8fxocffojLly/j/v37+Prrr7F7925s3rwZn376KWbOnImTJ09iypQp6NKlC6ysrCo8Xubm5gAAS0tL/Prrrxg6dCg6d+6stIORkRFeffXVMtuzUaNGWLhwIfbs2fNI/9fUn3/+iW+++QZVOI2JiIiIiEj/XVBJycublfD39wcAhIeH11pEVdWhQwdcvnwZVdgNqgfq23HNyspC586dcfbsWSWBrwvh4eEICAioN+1EREREREQa2VWrt8E3VCqVqtLXpUuXdB0m1aFVq1Zh/PjxdZqoExERERFRw1WrP91WF4rnQmdmZtbZk9V5FbP26eK4VtXx48cRFBSE7OxsqNVq/oGGiIiIiIi0pt5eWc/MzMSMGTNw/fp1AMCECRMQGxur46iopurTcbWwsEBGRgYMDAywY8cONGrUSNchERERERFRA1Hv56wTPc44Z52IiIiIqEHinHUiIiIiIiIifcNknYiIiIiIiEjPMFknIiIiIiIi0jNM1omIiIiIiIj0DJN1IiIiIiIiIj3DZJ2IiIiIiIhIzzBZJyIiIiIiItIzTNaJiIiIiIiI9AyTdSIiIiIiIiI9w2SdiIiIiIiISM8wWSciIiIiIiLSM0zWiYiIiIiIiPQMk3UiIiIiIiIiPWNU1RViY2Ph7+9fG7EQNVjJycmws7ODsbGxVutNTEzUan1ERERERKQfqpSs+/n51VYcRA2WWq1GbGwsioqK4OTkhFatWsHR0REGBjW/saVly5bo2bOnFqIkIiIiIiJ9ohIR0XUQRA1deno6IiIisGvXLuzbtw9WVlZ45ZVXMGzYMLzwwgtQqVS6DpGIiIiIiPTHLibrRHUsISEB27dvx/bt2/Hnn3+ibdu2GDZsGN555x20atVK1+EREREREZHuMVkn0qXTp09j27Zt2LZtG1JTU/HCCy9gxIgReP3112Fqaqrr8IiIiIiISDeYrBPpA7VajSNHjmDdunXYs2cPzM3NERAQgKFDh8LLy0vX4RERERERUd1isk6kb27duoWtW7di48aNuHjxIjp16oTg4GAMGTIE1tbWug6PiIiIiIhqH5N1In0WGxuLDRs2YOfOnTAwMMCbb76J4OBgPPXUU7oOjYiIiIiIag+TdaL6ICMjAzt37sSqVatw9uxZPPXUUwgKCsLbb78NCwsLXYdHRERERETaxWSdqL45evQo1q5di927d8PMzAwjRozAuHHj4OrqquvQiIiIiIhIO5isE9VXqamp+PLLL7F69WokJiZiwIABmDhxIp577jldh0ZERERERDWzy0DXERBR9djb22PatGmIi4vDnj17kJmZib59+6JLly5Yt24dsrOzdR0iERERERFVE6+sEzUgv/32G5YvX47w8HDY2Nhg7NixGDduHOzt7XUdGhERERERaY63wRM1RDdv3sTq1auxZs0a5OTkYOTIkQgJCUGbNm10HRoREREREVWOt8ETNUTNmzfHvHnzkJSUhDVr1mD//v1o164d+vfvjxMnTug6PCIiIiIiqgSTdaIGrFGjRhg2bBguXbqEPXv2IDk5GT169ICXlxciIyN1HR4REREREZWDyTrRY8DAwAD9+/fHr7/+in379sHExAQDBgxA9+7dsXv3bhQVFek6RCIiIiIiKoHJOtFjRKVS4Z///CcOHz6MEydOwMXFBf7+/ujUqRO2b98OtVqt6xCJiIiIiAhM1okeW927d8euXbtw5coVeHl54Z133oGbmxuWL1+OvLw8XYdHRERERPRY49PgiQgAcO3aNSxduhRffPEFmjVrhpCQEAQFBcHMzEzXoRERERERPW74021EVFpCQgIWL16M9evXo3HjxggJCcH48eNhbm6u69CIiIiIiB4XTNaJqGwpKSlYsmQJVq5cCQsLC0yZMgUTJkzglXYiIiIiotrHZJ2IKpaSkoJFixZh7dq1sLGxwQcffIDRo0ejUaNGug6NiIiIiKihYrJORJq5ffs2Fi9ejBUrVsDe3h5TpkxBcHAwTE1NdR0aEREREVFDw2SdiKqm+Pb45cuXw8HBASEhIRgzZgyvtBMRERERac+jyXpubi5++OEH/t4yUQPQvXt3uLi41ErdCQkJmD9/PjZu3IhWrVph9uzZePvtt2FoaFgr2yMiIiIieow8mqx/++23GDhwoK4CIiItGjx4ML766qta3ca1a9cwb948bNmyBe7u7vjkk0/w6quvQqVS1ep2iYiIiIgasF0GD5cUFhYCAESEL774qscvPz+/OrlDxsXFBf/+979x/vx5dOvWDQMHDsQzzzyDqKioWt82EREREVFD9UiyTkRUHe7u7tiyZQv++OMPtG7dGj4+PvD19cVvv/2m69CIiIiIiOodJutEpFUdO3ZEeHg4YmJiUFBQgO7du8PX1xdnz57VdWhERERERPUGk3UiqhXPPvssfvrpJ0RERCA5ORndunXDqFGjcOPGDV2HRkRERESk95isE1GtGjBgAM6cOYNNmzbh0KFDaN++PT766CNkZmbqOjQiIiIiIr3FZJ2Iap2BgQGGDBmCK1euYP78+VixYgXatGmD5cuXKw+1JCIiIiKi/2KyTkR1xsTEBBMnTsR//vMfBAYGYvr06ejUqRN27dql69CIiIiIiPQKk3UiqnN2dnZYuHAhzp07h06dOiEgIAA+Pj44c+aMrkMjIiIiItILTNaJSGfc3NwQHh6O2NhY5Obm4qmnnoK/vz/i4+N1HRoRERERkU4xWScinevRoweOHj2KnTt34tSpU3jiiScQGhqKjIwMXYdGRERERKQTTNaJSC+oVCr4+fnh4sWLWLBgAb744gu0bduWD6EjIiIioscSk3Ui0it8CB0REREREZN1ItJT5T2E7vTp07oOjYiIiIio1jFZJyK9VvwQuujoaNy/fx9PP/00AgMDkZycrOvQiIiIiIhqDZN1IqoXvL29cfz4cWzbtg0HDx6Eu7s7li5dioKCAl2HRkRERESkdbWarN+7d682q9cLycnJCA8Px/z583UdSq15HI4j1Q8qlQpvvvkmLl26hEmTJmHGjBno2LEj9u3bp+vQiIiIiIi0SuvJem5uLubPn4+ePXuiSZMm2q6+xkQEK1aswPTp09G3b194e3vj8uXL5ZZX5OLFi/j4448REBCArVu31tEePKpHjx6YOnWqVuuszeN49OhRhIaGQqVSQaVSYdiwYYiIiNDqNqrjyJEj8PPzU+IKDg5GTEyMrsOiMpibm2POnDm4cuUKevTogZdeegn9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\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.keras.utils.plot_model(model, 'dnn_model.png', show_shapes=False, rankdir='LR')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train the model\n",
    "\n",
    "To train the model, simply call [model.fit()](https://keras.io/models/model/#fit).\n",
    "\n",
    "Note that we should really use many more NUM_TRAIN_EXAMPLES (i.e. a larger dataset). We shouldn't make assumptions about the quality of the model based on training/evaluating it on a small sample of the full data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5\n",
      "312/312 [==============================] - 3s 10ms/step - loss: 88.9460 - rmse: 8.9355 - mse: 88.9460 - val_loss: 111.2182 - val_rmse: 10.5367 - val_mse: 111.2182\n",
      "Epoch 2/5\n",
      "312/312 [==============================] - 3s 9ms/step - loss: 96.8535 - rmse: 9.1739 - mse: 96.8536 - val_loss: 111.5715 - val_rmse: 10.5534 - val_mse: 111.5715\n",
      "Epoch 3/5\n",
      "312/312 [==============================] - 3s 8ms/step - loss: 101.4297 - rmse: 9.3561 - mse: 101.4297 - val_loss: 111.0815 - val_rmse: 10.5303 - val_mse: 111.0815\n",
      "Epoch 4/5\n",
      "312/312 [==============================] - 3s 8ms/step - loss: 97.6829 - rmse: 9.3463 - mse: 97.6829 - val_loss: 111.9293 - val_rmse: 10.5702 - val_mse: 111.9293\n",
      "Epoch 5/5\n",
      "312/312 [==============================] - 3s 9ms/step - loss: 94.8830 - rmse: 9.1620 - mse: 94.8831 - val_loss: 111.2204 - val_rmse: 10.5368 - val_mse: 111.2204\n"
     ]
    }
   ],
   "source": [
    "TRAIN_BATCH_SIZE = 32\n",
    "NUM_TRAIN_EXAMPLES = 10000 * 5 # training dataset repeats, so it will wrap around\n",
    "NUM_EVALS = 5  # how many times to evaluate\n",
    "NUM_EVAL_EXAMPLES = 10000 # enough to get a reasonable sample, but not so much that it slows down\n",
    "\n",
    "trainds = load_dataset('../../data/taxi-train*', TRAIN_BATCH_SIZE, tf.estimator.ModeKeys.TRAIN)\n",
    "evalds = load_dataset('../../data/taxi-valid*', 1000, tf.estimator.ModeKeys.EVAL).take(NUM_EVAL_EXAMPLES//1000)\n",
    "\n",
    "steps_per_epoch = NUM_TRAIN_EXAMPLES // (TRAIN_BATCH_SIZE * NUM_EVALS)\n",
    "\n",
    "history = model.fit(trainds, \n",
    "                    validation_data=evalds,\n",
    "                    epochs=NUM_EVALS, \n",
    "                    steps_per_epoch=steps_per_epoch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize the model loss curve\n",
    "\n",
    "Next, we will use matplotlib to draw the model's loss curves for training and validation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# plot\n",
    "import matplotlib.pyplot as plt\n",
    "nrows = 1\n",
    "ncols = 2\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "\n",
    "for idx, key in enumerate(['loss', 'rmse']):\n",
    "    ax = fig.add_subplot(nrows, ncols, idx+1)\n",
    "    plt.plot(history.history[key])\n",
    "    plt.plot(history.history['val_{}'.format(key)])\n",
    "    plt.title('model {}'.format(key))\n",
    "    plt.ylabel(key)\n",
    "    plt.xlabel('epoch')\n",
    "    plt.legend(['train', 'validation'], loc='upper left');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Predict with the model locally\n",
    "\n",
    "To predict with Keras, you simply call [model.predict()](https://keras.io/models/model/#predict) and pass in the cab ride you want to predict the fare amount for."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[11.430003]], dtype=float32)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.predict({\n",
    "    'pickup_longitude': tf.convert_to_tensor([-73.982683]),\n",
    "    'pickup_latitude': tf.convert_to_tensor([40.742104]),\n",
    "    'dropoff_longitude': tf.convert_to_tensor([-73.983766]),\n",
    "    'dropoff_latitude': tf.convert_to_tensor([40.755174]),\n",
    "    'passenger_count': tf.convert_to_tensor([3.0]),    \n",
    "}, steps=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, this is not realistic, because we can't expect client code to have a model object in memory. We'll have to export our model to a file, and expect client code to instantiate the model from that exported file."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Export the model for serving\n",
    "\n",
    "Let's export the model to a TensorFlow SavedModel format. Once we have a model in this format, we have lots of ways to \"serve\" the model, from a web application, from JavaScript, from mobile applications, etc."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Assets written to: ./export/savedmodel/20190922210532/assets\n"
     ]
    }
   ],
   "source": [
    "import shutil, os, datetime\n",
    "OUTPUT_DIR = './export/savedmodel'\n",
    "shutil.rmtree(OUTPUT_DIR, ignore_errors=True)\n",
    "EXPORT_PATH = os.path.join(OUTPUT_DIR, datetime.datetime.now().strftime('%Y%m%d%H%M%S'))\n",
    "tf.saved_model.save(model, EXPORT_PATH) # with default serving function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The given SavedModel SignatureDef contains the following input(s):\n",
      "  inputs['dropoff_latitude'] tensor_info:\n",
      "      dtype: DT_FLOAT\n",
      "      shape: (-1)\n",
      "      name: serving_default_dropoff_latitude:0\n",
      "  inputs['dropoff_longitude'] tensor_info:\n",
      "      dtype: DT_FLOAT\n",
      "      shape: (-1)\n",
      "      name: serving_default_dropoff_longitude:0\n",
      "  inputs['passenger_count'] tensor_info:\n",
      "      dtype: DT_FLOAT\n",
      "      shape: (-1)\n",
      "      name: serving_default_passenger_count:0\n",
      "  inputs['pickup_latitude'] tensor_info:\n",
      "      dtype: DT_FLOAT\n",
      "      shape: (-1)\n",
      "      name: serving_default_pickup_latitude:0\n",
      "  inputs['pickup_longitude'] tensor_info:\n",
      "      dtype: DT_FLOAT\n",
      "      shape: (-1)\n",
      "      name: serving_default_pickup_longitude:0\n",
      "The given SavedModel SignatureDef contains the following output(s):\n",
      "  outputs['fare'] tensor_info:\n",
      "      dtype: DT_FLOAT\n",
      "      shape: (-1, 1)\n",
      "      name: StatefulPartitionedCall:0\n",
      "Method name is: tensorflow/serving/predict\n",
      "./export/savedmodel/20190922210532\n",
      "./export/savedmodel/20190922210532/saved_model.pb\n",
      "./export/savedmodel/20190922210532/variables\n",
      "./export/savedmodel/20190922210532/variables/variables.index\n",
      "./export/savedmodel/20190922210532/variables/variables.data-00000-of-00001\n",
      "./export/savedmodel/20190922210532/assets\n"
     ]
    }
   ],
   "source": [
    "!saved_model_cli show --tag_set serve --signature_def serving_default --dir {EXPORT_PATH}\n",
    "!find {EXPORT_PATH}\n",
    "os.environ['EXPORT_PATH'] = EXPORT_PATH"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Deploy the model to AI Platform\n",
    "\n",
    "Next, we will use the `gcloud ai-platform` command to create a new version for our __taxifare__ model and give it the version name of __dnn__. \n",
    "\n",
    "Deploying the model will take 5 - 10 minutes. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "PROJECT=${PROJECT}\n",
    "BUCKET=${BUCKET}\n",
    "REGION=${REGION}\n",
    "MODEL_NAME=taxifare\n",
    "VERSION_NAME=dnn\n",
    "\n",
    "if [[ $(gcloud ai-platform models list --format='value(name)' | grep $MODEL_NAME) ]]; then\n",
    "    echo \"The model named $MODEL_NAME already exists.\"\n",
    "else\n",
    "    # create model\n",
    "    echo \"Creating $MODEL_NAME model now.\"\n",
    "    gcloud ai-platform models create --regions=$REGION $MODEL_NAME\n",
    "fi\n",
    "\n",
    "if [[ $(gcloud ai-platform versions list --model $MODEL_NAME --format='value(name)' | grep $VERSION_NAME) ]]; then\n",
    "    echo \"Deleting already the existing model $MODEL_NAME:$VERSION_NAME ... \"\n",
    "    gcloud ai-platform versions delete --model=$MODEL_NAME $VERSION_NAME\n",
    "    echo \"Please run this cell again if you don't see a Creating message ... \"\n",
    "    sleep 2\n",
    "fi\n",
    "\n",
    "# create model\n",
    "echo \"Creating $MODEL_NAME:$VERSION_NAME\"\n",
    "gcloud ai-platform versions create --model=$MODEL_NAME $VERSION_NAME --async \\\n",
    "       --framework=tensorflow --python-version=3.7 --runtime-version=2.1 \\\n",
    "       --origin=$EXPORT_PATH --staging-bucket=gs://$BUCKET"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Monitor the model creation at [GCP Console > AI Platform](https://console.cloud.google.com/mlengine/models/taxifare/) and once the model version `dnn` is created, proceed to the next cell.\n",
    "\n",
    "### Predict with model using `gcloud ai-platform predict`\n",
    "\n",
    "To predict with the model, we first need to create some data that the model hasn't seen before. Let's predict for a new taxi cab ride for you and two friends going from [from Kips Bay and heading to Midtown Manhattan](https://www.google.com/maps/dir/40.742104,-73.982683/'40.755174,-73.983766'/@40.7487493,-73.9892016,16z/data=!3m1!4b1!4m6!4m5!1m0!1m3!2m2!1d-73.983766!2d40.755174) for a total distance of 1.3 miles. How much would that cost?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing input.json\n"
     ]
    }
   ],
   "source": [
    "%%writefile input.json\n",
    "{\"pickup_longitude\": -73.982683, \"pickup_latitude\": 40.742104,\"dropoff_longitude\": -73.983766,\"dropoff_latitude\": 40.755174,\"passenger_count\": 3.0}  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FARE\n",
      "[11.430005073547363]\n",
      "\n",
      "\n",
      "To take a quick anonymous survey, run:\n",
      "  $ gcloud alpha survey\n",
      "\n"
     ]
    }
   ],
   "source": [
    "!gcloud ai-platform predict --model taxifare --json-instances input.json --version dnn"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the [next notebook](../05_feateng), we will improve this model through feature engineering."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright 2022 Google Inc.\n",
    "Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n",
    "http://www.apache.org/licenses/LICENSE-2.0\n",
    "Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
